package inet.app.model.util;

import inet.app.model.object.ContactModel;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.util.Log;

import com.google.common.base.Preconditions;

public class ContactVersionIIUtil {

	private final ContentResolver contentResolver;

	public static ContactVersionIIUtil mInstance;

	public static ContactVersionIIUtil getInstance(Context context) {
		if (mInstance == null) {
			mInstance = new ContactVersionIIUtil(context);
		}

		return mInstance;
	}

	private ContactVersionIIUtil(Context context) {
		contentResolver = context.getContentResolver();
	}

	public ContactModel getPersonNameContact(String phoneNumber) {
		Preconditions.checkNotNull(phoneNumber);

		boolean stop = false;
		String personNameContact = "";
		ContactModel contact = new ContactModel();

		Cursor cContact = contentResolver.query(
				ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

		if (cContact != null) {
			if (cContact.moveToFirst()) {
				do {

					String id = cContact.getString(cContact
							.getColumnIndex(ContactsContract.Contacts._ID));

					String name = cContact
							.getString(cContact
									.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

					if (Integer
							.parseInt(cContact.getString(cContact
									.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {

						Cursor cPhone = contentResolver
								.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
										null,
										ContactsContract.CommonDataKinds.Phone.CONTACT_ID
												+ " = ?", new String[] { id },
										null);

						if (cPhone != null) {
							if (cPhone.moveToFirst()) {
								do {
									String number = cPhone
											.getString(cPhone
													.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

									Log.d("test_number", ContactUltil
											.removeHyphenInPhoneNumber(number)
											.trim());

									if (ContactUltil
											.removeHyphenInPhoneNumber(number)
											.trim().replaceAll("\\s", "")
											.equalsIgnoreCase(phoneNumber)) {
										personNameContact = name;
										contact.contactId = id;
										contact.contactName = name;
										contact.phoneNumber = phoneNumber;
										stop = true;
										break;
									}
								} while (cPhone.moveToNext());
							}
						}

						cPhone.close();
					}
					if (stop) {
						break;
					}
				} while (cContact.moveToNext());
			}
			cContact.close();
		}

		return personNameContact.equals("") ? null : contact;
	}

	public void addContact(String displayName, String phoneNumber, Bitmap photo) {

		ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.RawContacts.CONTENT_URI)
				.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
				.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
				.build());

		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.Data.CONTENT_URI)
				.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
				.withValue(
						ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
				.withValue(
						ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
						displayName).build());

		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.Data.CONTENT_URI)
				.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
				.withValue(
						ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
				.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,
						phoneNumber)
				.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
						ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
				.build());

		ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
		if (photo != null) {
			photo.compress(Bitmap.CompressFormat.PNG, 100, arrayOutputStream);
		}

		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.Data.CONTENT_URI)
				.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
				.withValue(
						ContactsContract.Data.MIMETYPE,
						ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
				.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO,
						arrayOutputStream.toByteArray()).build());
		try {
			contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
		} catch (Exception e) {
			Log.e("contactError", e.toString());
		}

	}

	public boolean checkExistPhoneNumber(String phoneNumber) {
		boolean result = false, isStop = false;

		Cursor cContact = contentResolver.query(
				ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

		if (cContact != null) {
			if (cContact.moveToFirst()) {
				do {
					String id = cContact.getString(cContact
							.getColumnIndex(ContactsContract.Contacts._ID));

					if (Integer
							.parseInt(cContact.getString(cContact
									.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
						Cursor cPhone = contentResolver
								.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
										null,
										ContactsContract.CommonDataKinds.Phone.CONTACT_ID
												+ " = ?", new String[] { id },
										null);

						while (cPhone.moveToNext()) {
							String number = cPhone
									.getString(cPhone
											.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
							if (ContactUltil.removeHyphenInPhoneNumber(number)
									.equals(phoneNumber)) {
								result = true;
								isStop = true;
								break;
							}
						}
						cPhone.close();

						if (isStop) {
							break;
						}
					}

				} while (cContact.moveToNext());

				cContact.close();
			}
		}

		return result;
	}

	public ArrayList<ContactModel> getListContact() {
		ArrayList<ContactModel> contactModels = null;
		ContactModel model;
		String id, name, number, photo, typeContact;

		Cursor cContact = contentResolver.query(
				ContactsContract.Contacts.CONTENT_URI, null, null, null,
				ContactsContract.Contacts.DISPLAY_NAME);

		if (cContact != null) {
			contactModels = new ArrayList<ContactModel>();
			if (cContact.moveToFirst()) {
				do {
					model = new ContactModel();
					id = cContact.getString(cContact
							.getColumnIndex(ContactsContract.Contacts._ID));
					model.contactId = id;
					name = cContact
							.getString(cContact
									.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
					model.contactName = name;

					Cursor cEmail = contentResolver.query(
							ContactsContract.CommonDataKinds.Email.CONTENT_URI,
							null,
							ContactsContract.CommonDataKinds.Email.CONTACT_ID
									+ " = ?", new String[] { id }, null);

					if (cEmail != null) {
						if (cEmail.moveToFirst()) {
							model.email = cEmail
									.getString(cEmail
											.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
						}
					}

					cEmail.close();

					if (Integer
							.parseInt(cContact.getString(cContact
									.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {

						Cursor cPhone = contentResolver
								.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
										null,
										ContactsContract.CommonDataKinds.Phone.CONTACT_ID
												+ " = ?", new String[] { id },
										null);

						if (cPhone != null) {
							if (cPhone.moveToFirst()) {
								number = cPhone
										.getString(cPhone
												.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
								model.phoneNumber = number;
							}
						}
						cPhone.close();
					}

					contactModels.add(model);
				} while (cContact.moveToNext());
				cContact.close();
			}
		}

		return contactModels;
	}

	/**
	 * Only load contact with name and phone number
	 * 
	 * @return
	 */
	public List<ContactModel> getListContactSimple() {
		List<ContactModel> listContact = new ArrayList<ContactModel>();
		Cursor phones = contentResolver.query(
				ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,
				null, null);
		ContactModel contact;
		while (phones.moveToNext()) {

			String name = phones
					.getString(phones
							.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));

			String phoneNumber = phones
					.getString(phones
							.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

			contact = new ContactModel();
			contact.setContactName(name);
			contact.setPhoneNumber(phoneNumber);
			listContact.add(contact);
		}
		phones.close();

		// sort list contact
		if (listContact != null && listContact.size() != 0) {
			Collections.sort(listContact, new Comparator<ContactModel>() {
				@Override
				public int compare(ContactModel lhs, ContactModel rhs) {
					return lhs.getContactName().compareTo(rhs.getContactName());
				}
			});
		}
		return listContact;
	}

//	public byte[] openPhoto(long contactId) {
//		Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI,
//				contactId);
//		Uri photoUri = Uri.withAppendedPath(contactUri,
//				Contacts.Photo.CONTENT_DIRECTORY);
//		Cursor cursor = contentResolver.query(photoUri,
//				new String[] { Contacts.Photo.PHOTO }, null, null, null);
//		if (cursor == null) {
//			return null;
//		}
//		try {
//			if (cursor.moveToFirst()) {
//				byte[] data = cursor.getBlob(0);
//				if (data != null) {
//					return new ByteArrayInputStream(data);
//				}
//			}
//		} finally {
//			cursor.close();
//		}
//		return null;
//	}

}
